using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using HarmonyLib;
using Newtonsoft.Json;
using UnityEngine;

namespace TheWorldOfKongfuEasyMod;

[HarmonyPatch(typeof(BattleController))]
[HarmonyPatch("LevelUpCheckProcess")]
public static class Patch_BattleController_CharacterExp
{
    public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
    {
        var codeMatcher = new CodeMatcher(instructions, generator);


        codeMatcher.MatchForward(false, new CodeMatch(OpCodes.Ldfld, typeof(BattleObject).GetField("m_FinalAddExp", 
            BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
        );
        if (!codeMatcher.IsValid)
        {
            throw new InvalidOperationException("Can't find m_FinalAddExp");
        }

        codeMatcher.Advance(1);
        codeMatcher.InsertAndAdvance(
            new CodeInstruction(OpCodes.Conv_R4),
            new CodeInstruction(OpCodes.Ldc_R4,Main.Setting._010multipleCharacterExp.Value),
            new CodeInstruction(OpCodes.Mul),
            new CodeInstruction(OpCodes.Call,typeof(Mathf).GetMethod("RoundToInt", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
        );
        return codeMatcher.Instructions();
    }
}[HarmonyPatch(typeof(BattleObject ))]
[HarmonyPatch("SkillLevelUpCheckProcess")]
public static class Patch_BattleObject_SkillExp
{
    public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
    {
        var codeMatcher = new CodeMatcher(instructions, generator);


        codeMatcher.MatchForward(false, new CodeMatch(OpCodes.Callvirt, typeof(KongFuData).GetMethod("CheckLevelUp", 
            BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new []{typeof(float),typeof(float),typeof(float),typeof(CharaData)},null))
        );
        if (!codeMatcher.IsValid)
        {
            throw new InvalidOperationException("Can't find CheckLevelUp");
        }
        codeMatcher.MatchBack(false, new CodeMatch(OpCodes.Ldfld, typeof(BattleObject).GetField("m_FinalAddExp", 
            BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
        );
        if (!codeMatcher.IsValid)
        {
            throw new InvalidOperationException("Can't find m_FinalAddExp");
        }
        codeMatcher.Advance(2);
        codeMatcher.InsertAndAdvance(
            new CodeInstruction(OpCodes.Ldc_R4,Main.Setting._011multipleWuGongExp.Value),
            new CodeInstruction(OpCodes.Mul)
        );
        return codeMatcher.Instructions();
    }
}

[HarmonyPatch(typeof(BattleController))]
[HarmonyPatch("Update")]
public static class Patch_BattleController_Update
{
    public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
    {
        var codeMatcher = new CodeMatcher(instructions, generator);


        codeMatcher.MatchForward(true, 
            new CodeMatch(OpCodes.Ldarg_0),
            new CodeMatch(OpCodes.Ldc_I4_3),
            new CodeMatch(OpCodes.Call, 
            typeof(BattleController).GetMethod("SetFlowState", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)),
            new CodeMatch(OpCodes.Ret)
            
            );
        if (!codeMatcher.IsValid)
        {
            throw new InvalidOperationException("Can't find isRoundActionFinish");
        }

        codeMatcher.InsertAndAdvance(
            new CodeInstruction(OpCodes.Ldarg_0),
            new CodeInstruction(OpCodes.Call, typeof(Patch_BattleController_Update).GetMethod("Do", BindingFlags.Static | BindingFlags.NonPublic))
        );
        return codeMatcher.Instructions();
    }

    static void Do(BattleController battleController)
    {
        if (Data.isAutoBattle )
        {
            if(battleController.AutoBattle)
                return;
            battleController.m_MenuController.m_menuState = BattleMenuState.CancelAutoBattleShow;
            battleController.AutoBattle = true;
            battleController.isLostControl = true;
            battleController.SetFlowState(BattleControllerFlow.CharacterInit);
        }
        else
        {
            if(!battleController.AutoBattle)
                return;
            battleController.m_MenuController.m_menuState = BattleMenuState.None;
            battleController.AutoBattle = false;
        }
    }
}

[HarmonyPatch(typeof(BattleController))]
[HarmonyPatch("InitEnemiesRandom")]
public static class Patch_BattleController_InitEnemiesRandom
{
    static bool Prefix(ref BattleController __instance,out List<gang_b04Table.Row> __result)
    {
        List<gang_b04Table.Row> list = JsonConvert.DeserializeObject<List<gang_b04Table.Row>>(JsonConvert.SerializeObject(SharedData.Instance(false).b04RamdonBattleRowList));
        if (SharedData.Instance(false).SpecialRandomFightGID.Equals(""))
        {
            System.Random random = new System.Random();
            List<int> list2 = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
            for (int i = 0; i < list.Count; i++)
            {
                int num = random.Next(list2.Count);
                int num2 = list2[num];
                list2.RemoveAt(num);
                list[i].ID = "Enemy" + num2;
                list[i].LER = "0";
                list[i].LER1 = "10";
            }
        }
        __result = list;
        return false;
    }
}